﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace NFit.WordML
{
    public static class WordStyleExtensions
    {
        public static Dictionary<string, string> GetStyleIdAndName(
            MainDocumentPart mainPart)
        {
            Dictionary<string, string> res = new Dictionary<string, string>();
            StyleDefinitionsPart stylePart =
                mainPart.StyleDefinitionsPart;

            foreach(var styleElt in stylePart.Styles.Descendants<StyleName>())
            {
                Style style = ((Style) styleElt.Parent);
                res.Add(style.StyleId, style.StyleName.Val);
            }

            return res;
        }

        public static string GetStyleIdFromStyleName(
            MainDocumentPart mainPart, string styleName)
        {
            StyleDefinitionsPart stylePart = 
                mainPart.StyleDefinitionsPart;

            string styleId = stylePart.Styles
                .Descendants<StyleName>()
                .Where(s => s.Val.Value.Equals(styleName))
                .Select(n => ((Style)n.Parent).StyleId)
                .FirstOrDefault();

            return styleId ?? styleName;
        }

        public static string GetStyleNameFromStyleId(
            MainDocumentPart mainPart, string styleId)
        {
            StyleDefinitionsPart stylePart =
                mainPart.StyleDefinitionsPart;

            string styleName = stylePart.Styles
                .Descendants<StyleName>()
                .Where(n => ((Style)n.Parent).StyleId == styleId)
                .Select(s => s.Val.Value.ToString())
                .FirstOrDefault();

            return styleName ?? styleId;
        }

        public static IEnumerable<Paragraph> ParagraphsByStyleName(
            this MainDocumentPart mainPart, string styleName)
        {
            string styleId = GetStyleIdFromStyleName(mainPart, styleName);

            IEnumerable<Paragraph> paraList = mainPart.Document
                .Descendants<Paragraph>()
                .Where(p => IsParagraphInStyle(p, styleId));

            return paraList;
        }

        public static bool IsParagraphInStyle(Paragraph p, 
                                              string styleId)
        {
            ParagraphProperties pPr = p
                .GetFirstChild<ParagraphProperties>();

            if (pPr != null)
            {
                ParagraphStyleId paraStyle = pPr.ParagraphStyleId;
                if (paraStyle != null)
                {
                    return paraStyle.Val.Value.Equals(styleId);
                }
            }
            return false;
        }

        public static string StyleId(this Paragraph p)
        {
            ParagraphProperties pPr = p
                .GetFirstChild<ParagraphProperties>();

            if (pPr != null)
            {
                ParagraphStyleId paraStyle = pPr.ParagraphStyleId;
                if (paraStyle != null)
                {
                    return paraStyle.Val.Value;
                }
            }
            return null;
        }


        public static IEnumerable<Run> RunsByStyleName(
            this MainDocumentPart mainPart, string styleName)
        {
            string styleId = GetStyleIdFromStyleName(mainPart, styleName);

            IEnumerable<Run> runList = mainPart.Document
                .Descendants<Run>()
                .Where(r => IsRunInStyle(r, styleId));

            return runList;
        }

        private static bool IsRunInStyle(Run r, string styleId)
        {
            RunProperties rPr = r.GetFirstChild<RunProperties>();

            if (rPr != null)
            {
                RunStyle runStyle = rPr.RunStyle;
                if (runStyle != null)
                {
                    return runStyle.Val.Value.Equals(styleId);
                }
            }
            return false;
        }

        public static IEnumerable<Table> TablesByStyleName(
            this MainDocumentPart mainPart, string styleName)
        {
            string styleId = GetStyleIdFromStyleName(mainPart, styleName);
            IEnumerable<Table> tableList = mainPart.Document
                .Descendants<Table>()
                .Where(t => IsTableInStyle(t, styleId));

            return tableList;
        }

        public static bool IsInStyle(this Table tbl, string styleId)
        {
            return IsTableInStyle(tbl, styleId);
        }

        public static bool IsTableInStyle(Table tbl, string styleId)
        {
            TableProperties tblPr = tbl.GetFirstChild<TableProperties>();

            if (tblPr != null)
            {
                TableStyle tblStyle = tblPr.TableStyle;
                if (tblStyle != null)
                {
                    return tblStyle.Val.Value.Equals(styleId);
                }
            }
            return false;
        }

        public static string StyleId(this Table tbl)
        {
            TableProperties tblPr = tbl.GetFirstChild<TableProperties>();
            return tblPr.TableStyle.Val ?? string.Empty;
        }
    }
}